package cn.iocoder.devlop.module.annual.report.entuser.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.iocoder.devlop.framework.common.pojo.PageResult;
import cn.iocoder.devlop.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.devlop.module.annual.report.entuser.controller.vo.EntuserBaseVO;
import cn.iocoder.devlop.module.annual.report.entuser.controller.vo.EntuserExportReqVO;
import cn.iocoder.devlop.module.annual.report.entuser.controller.vo.EntuserPageReqVO;
import cn.iocoder.devlop.module.annual.report.entuser.controller.vo.EntuserUpdateReqVO;
import cn.iocoder.devlop.module.annual.report.entuser.dal.EntuserMapper;
import cn.iocoder.devlop.module.annual.report.entuser.dal.dataobject.EntuserDO;
import cn.iocoder.devlop.module.annual.report.marpripinfo.controller.vo.CheckResp;
import cn.iocoder.devlop.module.annual.report.marpripinfo.controller.vo.LoginReqVO;
import cn.iocoder.devlop.module.annual.report.marpripinfo.service.MarpripinfoService;
import cn.iocoder.devlop.module.annual.report.utils.SmsApi;
import cn.iocoder.devlop.module.system.controller.admin.auth.vo.AuthLoginRespVO;
import cn.iocoder.devlop.module.system.enums.logger.LoginLogTypeEnum;
import cn.iocoder.devlop.module.system.service.auth.AdminAuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static cn.iocoder.devlop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.devlop.module.annual.report.enums.ErrorCodeConstants.*;
import static cn.iocoder.devlop.module.system.enums.ErrorCodeConstants.*;

/**
 * 用户信息 Service 实现类
 *
 * @author sunhao
 */
@Service
@Validated
@Slf4j
public class EntuserServiceImpl implements EntuserService {

    @Resource
    private EntuserMapper entuserMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private AdminAuthService adminAuthService;

    @Resource
    private MarpripinfoService marpripinfoService;

    @Value("${devlop.anonymous-authentication:}")
    private String anonymousAuthentication;

    @Override
    public void createEntuser(EntuserBaseVO baseVO) {
        String redisKey = "register" + baseVO.getPhone() + baseVO.getRegno();
        String SMSCode = stringRedisTemplate.opsForValue().get(redisKey);
        if (StrUtil.isEmpty(SMSCode)) {
            throw exception(SMS_CODE_EXPIRED);
        }
        if (!baseVO.getSMSCode().equals(SMSCode)) {
            throw exception(SMS_CODE_NOT_CORRECT);
        }
        // 验证抛异常
        CheckResp checkResp = marpripinfoService.checkMarpripinfo(baseVO.getRegno());
        if (null == checkResp) {
            throw exception(MARPRIPINFO_NOT_EXISTS);
        }
        if (!checkResp.getOpstate().equals("06") && !checkResp.getOpstate().equals("97")) {
            throw exception(MARPRIPINFO_STATE_ERROR);
        }
        if (null != checkResp.getLinkman()) {
            throw exception(MARPRIPINFO_HAS_ENTUSER);
        }
        if (!baseVO.getLerep().equals(checkResp.getLerep()) || !baseVO.getLegcerno().equals(checkResp.getLegcerno())) {
            throw exception(MARPRIPINFO_LEREP_ERROR);
        }
        // 等不到他们的接口，先自己进行实现
        EntuserDO entuserDO = new EntuserDO();
        entuserDO.setMarprid(checkResp.getId());
        entuserDO.setRegno(checkResp.getRegno());
        entuserDO.setEnttype(checkResp.getEnttype());
        // TODO 不知道初始密码生成规则，先随意生成了
        entuserDO.setLoginpwd(SecureUtil.md5(checkResp.getRegno() + "666666"));
        entuserDO.setLinkman(baseVO.getLinkman());
        entuserDO.setIdeneffeno(baseVO.getIdeneffeno());
        entuserDO.setPhone(baseVO.getPhone());
        // TODO 知道字典值后根据字典去设置
        entuserDO.setFromtype("01");
        entuserDO.setCreatedate(LocalDateTime.now());
        entuserDO.setUpdatetime(LocalDateTime.now());
        entuserDO.setLerep(checkResp.getLerep());
        // TODO 同上缺字典
        entuserDO.setCertype("10");
        if (null != checkResp.getUniscid()) {
            entuserDO.setUniscid(checkResp.getUniscid());
        }
        entuserMapper.insert(entuserDO);
        // 调用他们的接口 TODO
//        HttpResponse execute = HttpRequest.post("").body(JSONUtil.toJsonStr(baseVO)).execute();
//        if (execute.getStatus() == HttpStatus.HTTP_OK) {
//            String body = execute.body();
//        }
    }

    @Override
    public void updateEntuser(EntuserUpdateReqVO updateReqVO) {
        String redisKey = "change" + updateReqVO.getPhone() + updateReqVO.getRegno();
        String SMSCode = stringRedisTemplate.opsForValue().get(redisKey);
        if (StrUtil.isEmpty(SMSCode)) {
            throw exception(SMS_CODE_EXPIRED);
        }
        if (!updateReqVO.getSMSCode().equals(SMSCode)) {
            throw exception(SMS_CODE_NOT_CORRECT);
        }
        // 效验数据
        EntuserDO entuserDO = getEntuserByIdeneffeno(updateReqVO.getExideneffeno(), updateReqVO.getRegno());
        if (null == entuserDO) {
            throw exception(ENTUSER_NOT_EXISTS);
        }
        if (!updateReqVO.getExlinkman().equals(entuserDO.getLinkman()) || !updateReqVO.getExideneffeno().equals(entuserDO.getIdeneffeno()) || !updateReqVO.getExphone().equals(entuserDO.getPhone())) {
            throw exception(ENTUSER_HAS_ERROR);
        }
        // 他们的接口还没提供先自己实现
        entuserDO.setLinkman(updateReqVO.getLinkman());
        entuserDO.setIdeneffeno(updateReqVO.getIdeneffeno());
        entuserDO.setPhone(updateReqVO.getPhone());
        entuserMapper.updateById(entuserDO);
        // 根据他们的接口处理数据
        // 调用他们的接口 TODO
//        HttpResponse execute = HttpRequest.post("").body(JSONUtil.toJsonStr(baseVO)).execute();
//        if (execute.getStatus() == HttpStatus.HTTP_OK) {
//            String body = execute.body();
//        }
    }

    @Override
    public void deleteEntuser(Long id) {
        // 校验存在
        validateEntuserExists(id);
        // 删除
        entuserMapper.deleteById(id);
    }

    private void validateEntuserExists(Long id) {
        if (entuserMapper.selectById(id) == null) {
            throw exception(ENTUSER_NOT_EXISTS);
        }
    }

    @Override
    public EntuserDO getEntuser(Long id) {
        return entuserMapper.selectById(id);
    }

    @Override
    public List<EntuserDO> getEntuserList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return ListUtil.empty();
        }
        return entuserMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<EntuserDO> getEntuserPage(EntuserPageReqVO pageReqVO) {
        return entuserMapper.selectPage(pageReqVO);
    }

    @Override
    public List<EntuserDO> getEntuserList(EntuserExportReqVO exportReqVO) {
        return entuserMapper.selectList(exportReqVO);
    }

    @Override
    public EntuserDO getEntuserByIdeneffeno(String ideneffeno, String regno) {
//        EntuserDO entuser = getEntuserFromAll(regno);
//        if (ObjUtil.isEmpty(entuser)){
//            return null;
//        }else if (StrUtil.equals(entuser.getIdeneffeno(),ideneffeno)){
//            return entuser;
//        }else {
//            return null;
//        }

        return entuserMapper.selectEntuserByIdeneffeno(ideneffeno, regno);
    }

    @Override
    public void sentSMSCode(String phone, String regno, String type) {
        String redisKey = type + phone + regno;
        String old = stringRedisTemplate.opsForValue().get(redisKey);
        // 如果是登录，需要效验是否有这个联络员
        if (type.equals("login")) {
//            EntuserDO entuser = getEntuserFromAll(regno);
//            if (ObjUtil.isEmpty(entuser)){
//                throw exception(ENTUSER_NOT_EXISTS);
//            }else if (StrUtil.equals(entuser.getPhone(),phone)){
//                throw exception(PHONE_ERROR);
//            }
            EntuserDO entuserDO = entuserMapper.selectOne("phone", phone, "regno", regno);
            if (ObjUtil.isEmpty(entuserDO)) {
                throw exception(ENTUSER_NOT_EXISTS);
            }
        }
        String code = RandomUtil.randomNumbers(6);
        SmsApi.sendSmsApiMessage(phone, code);
        stringRedisTemplate.opsForValue().set(redisKey, code, 300, TimeUnit.SECONDS);
    }


    @Override
    public AuthLoginRespVO entUserLogin(LoginReqVO loginReqVO) {
        // 校验验证码
        if (!StrUtil.equals(anonymousAuthentication, loginReqVO.getSMSCode())) {
            String value = stringRedisTemplate.opsForValue().get("login" + loginReqVO.getPhone() + loginReqVO.getRegno());
            if (StrUtil.isEmpty(value)) {
                throw exception(SMS_CODE_EXPIRED);
            }
            if (!value.equals(loginReqVO.getSMSCode())) {
                throw exception(SMS_CODE_NOT_CORRECT);
            }
        }
        // 获得用户信息
        EntuserDO entuserDO = entuserMapper.selectByPhoneAndRegno(loginReqVO.getPhone(), loginReqVO.getRegno());
        if (entuserDO == null) {
            throw exception(USER_NOT_EXISTS);
        }
        marpripinfoService.checkState(loginReqVO.getRegno());
        // 创建 Token 令牌，记录登录日志
        AuthLoginRespVO success = adminAuthService.createTokenAfterLoginSuccess(entuserDO.getId(), loginReqVO.getPhone(), LoginLogTypeEnum.LOGIN_MOBILE);
        // 删除 短信验证码
        stringRedisTemplate.delete(loginReqVO.getPhone() + loginReqVO.getRegno());
        return success;
    }

    @Override
    public EntuserDO getEntuserByRegno(String regno) {
        LambdaQueryWrapperX<EntuserDO> wrapper = new LambdaQueryWrapperX<>();
        wrapper.eq(EntuserDO::getRegno, regno);
        return entuserMapper.selectOne(wrapper);
    }

//    @Override
//    @DS("tp")
//    public EntuserDO getEntuserFromTP(String regno) {
//        LambdaQueryWrapperX<EntuserFromTPDO> wrapper = new LambdaQueryWrapperX<>();
//        wrapper.eq(EntuserFromTPDO::getRegno,regno);
//        EntuserFromTPDO entuserFromTPDO = entuserTPMapper.selectOne(wrapper);
//        return BeanUtil.toBean(entuserFromTPDO, EntuserDO.class);
//    }
//
//    @Override
//    public EntuserDO getEntuserFromAll(String regno){
//        EntuserDO entuserFromUs = getEntuserByRegno(regno);
//        EntuserDO entuserFromTP = getEntuserFromTP(regno);
//        if (ObjUtil.isEmpty(entuserFromUs) && ObjUtil.isEmpty(entuserFromTP)){
//            return null;
//        }
//        if (ObjUtil.isEmpty(entuserFromUs) && ObjUtil.isNotEmpty(entuserFromTP)){
//            entuserMapper.insert(entuserFromTP);
//            return entuserFromTP;
//        }
//        if (ObjUtil.isNotEmpty(entuserFromUs) && ObjUtil.isNotEmpty(entuserFromTP)){
//            if (entuserFromTP.getUpdatetime().isAfter(entuserFromUs.getUpdatetime())){
//                LambdaQueryWrapperX<EntuserDO> deleteWrapper = new LambdaQueryWrapperX<>();
//                deleteWrapper.eq(EntuserDO::getRegno,entuserFromUs.getRegno());
//                entuserMapper.delete(deleteWrapper);
//                entuserMapper.insert(entuserFromTP);
//                return getEntuserByRegno(regno);
//            }
//        }
//        return entuserFromUs;
//    }


}
